A
append output symbol (>>)
argv
atexit
C
calloc
command-line arguments
D
dynamic arrays
E
event
exit
EXIT_FAILURE
EXIT_SUCCESS
extern
extern "C"
external linkage
F
F floating-point suffix
f floating-point suffix
floating-point exception
G
goto statement
I
illegal instruction
internal linkage
interrupt
L
L floating-point suffix
l floating-point suffix
L integer suffix
l integer suffix
M
make
makefile
P
pipe (|)
piping
R
raise
realloc
redirect output symbol (>)
S
segmentation violation
signal
signal handling library
signal.h
static
stdarg.h
T
trap unexpected event
U
union
unsigned
unsigned long
V
va_arg
va_end
va_list
va_start
variable-length argument list
volatile type qualifier

Some systems do not support global variable names or function names of more than 6 characters. This should be considered when writing programs that will be ported to multiple platforms.

If data is stored in a union as one type and referenced as another type, the results are implementation dependent.

Some unions may not port easily to other computer systems. Whether a union is portable or not often depends on the storage alignment requirements for the union member data types on a given system.
The amount of storage required to store a union is implementation dependent.

We'll use a signal I have tried and found
far-reaching and easy to yell. Waa-hoo!
Zane Grey

Use it up, wear it out; Make it do, or do without.
Anonymous

It is quite a three-pipe problem.
Sir Arthur Conan Doyle

But yet an union in partition;
William Shakespeare

I could never make out what those damned dots meant.
Winston Churchill

Fig. 18.1 The type and the macros defined in header stdarg.h.
Fig. 18.2 Using variable-length argument lists.
Fig. 18.3 Using command-line arguments.
Fig. 18.4 Using functions exit and atexit.
Fig. 18.5 The signals defined in header signal.h.
Fig. 18.6 Using signal handling.
Fig. 18.7 Using goto.
Fig. 18.8 Printing the value of a union in both member data types.
Fig. 18.9 Using an anonymous union.

Figure 18.1 - The type and the macros defined in header stdarg.h.
Figure 18.5 - The signals defined in header signal.h.
Answer 18.1
a) redirect input (<).
b) redirect output (>).
c) append output (>>).
d) pipe (|).
e) ellipsis (...).
f) va_start.
g) va_arg.
h) va_end.
i) argc.
j) argv.
k) make, makefile.
l) exit.
m) atexit.
n) const.
o) suffix.
p) signal.
q) raise.
r) calloc.
s) realloc.
t) union.
u) union.
Answer 18.3
The solution to this exercise can be found on your Cyber Classroom CD. Copy the file cpphtp2/answers/P18_03.zip to your hard drive and unzip the program code.

Answer 18.8
The solution to this exercise can be found on your Cyber Classroom CD. Copy the file cpphtp2/answers/P18_08.zip to your hard drive and unzip the program code.

Answer 18.10
The solution to this exercise can be found on your Cyber Classroom CD. Copy the file cpphtp2/answers/P18_10.zip to your hard drive and unzip the program code.

Exercise 18.1
Fill in the blanks in each of the following:
a) Symbol ________ redirects input data from the keyboard to come from a file.
b) The ________ symbol is used to redirect the screen output to be placed in a file.
c) The ________ symbol is used to append the output of a program to the end of a file.
d) A ________ is used to direct the output of a program as the input of another program.
e) An ________ in the parameter list of a function indicates that the function can receive a variable number of arguments.
f) Macro ________ must be invoked before the arguments in a variable-length argument list can be accessed.
g) Macro ________ is used to access the individual arguments of a variable- length argument list.
h) Macro ________ facilitates a normal return from a function whose variable argument list was referred to by macro va_start.
i) Argument ________ of main receives the number of arguments in a command line.
j) Argument ________ of main stores command-line arguments as character strings.
k) The UNIX utility ________ reads a file called ________ that contains instructions for compiling and linking a program consisting of multiple source files. The utility only recompiles a file if the file has been modified since it was last compiled.
l) Function ________ forces a program to terminate execution.
m) Function ________ registers a function to be called upon normal termination of the program.
n) Type qualifier ________ indicates that an object should not be modified after it is initialized.
o) An integer or floating-point ________ can be appended to an integer or floating-point constant to specify the exact type of the constant.
p) Function ________ can be used to trap unexpected events.
q) Function ________ generates a signal from within a program.
r) Function ________ dynamically allocates memory for an array and initializes the elements to zero.
s) Function ________ changes the size of a block of dynamically allocated memory.
t) A ________ is a class containing a collection of variables that occupy the same memory, but at different times.
u) The ________ keyword is used to introduce a union definition.

Exercise 18.2
Write a program that calculates the product of a series of integers that are passed to function product using a variable-length argument list. Test your function with several calls each with a different number of arguments.


Exercise 18.3
Write a program that prints the command-line arguments of the program.


Exercise 18.4
Write a program that sorts an integer array into ascending order or descending order. The program should use command-line arguments to pass either argument -a for ascending order or -d for descending order. (Note: This is the standard format for passing options to a program in UNIX.)


Exercise 18.5
Read the manuals for your system to determine what signals are supported by the signal handling library (signal.h). Write a program with signal handlers for the signals SIGABRT and SIGINT. The program should test the trapping of these signals by calling function abort to generate a signal of type SIGABRT, and by typing <ctrl> c to generate a signal of type SIGINT.


Exercise 18.6
Write a program that dynamically allocates an array of integers. The size of the array should be input from the keyboard. The elements of the array should be assigned values input from the keyboard. Print the values of the array. Next, reallocate the memory for the array to half of the current number of elements. Print the values remaining in the array to confirm that they match the first half of the values in the original array.

Exercise 18.7
Write a program that takes two file name command-line arguments, reads the characters from the first file one at a time, and writes the characters in reverse order to the second file.


Exercise 18.8
Write a program that uses goto statements to simulate a nested looping structure that prints a square of asterisks, as follows:


*****

* *

* *

* *

*****


The program should use only the following three output statements:

cout << '*';


cout << ' ';


cout << endl; 

Exercise 18.9
Provide the definition for union Data containing char c, short s, long l, float f, and double d.


Exercise 18.10
Create union Integer with members char c, short s, int i, and long l. Write a program that inputs values of type char, short, int and long, and stores the values in union variables of type union Integer. Each union variable should be printed as a char, a short, an int, and a long. Do the values always print correctly?


Exercise 18.11
Create union FloatingPoint with members float f, double d, and long double l. Write a program that inputs value of type float, double, and long double, and stores the values in union variables of type union FloatingPoint. Each union variable should be printed as a float, a double, and a long double. Do the values always print correctly?


Exercise 18.12
Given the union

union A {

float y;

char *z;

};

which of the following are correct statements for initializing the union?

a)  A p = B;  // B is of same type as A

b) A q = x; // x is a float

c) A r = 3.14159;

d) A s = { 79.63 };

e) A t = { "Hi There!" };


f)  A u = { 3.14159, "Pi" };



Global variables increase performance because they can be accessed directly by any function--the overhead of passing data to functions is eliminated.

The goto statement can be used to exit deeply nested control structures efficiently.

Using unions conserve storage.

Figure 18.2 Using variable-length argument lists.



Figure 18.3 Using command-line arguments.
Note: This program must be executed from the command line. Save to disk and run the executable file from the directory it is saved in. You supply the program command line arguments consisting of the name of the original file and the name of the file the contents of the original file are to be copied to.



Figure 18.4 Using functions exit and atexit.



Figure 18.6 Using signal handling.



Figure 18.7 Using goto.



Figure 18.8 Printing the value of a union in both member data types.



Figure 18.9 Using an anonymous union.



* To be able to redirect keyboard input to come from a file and redirect screen output into a file. * To be able to write functions that use variable-length argument lists. * To be able to process command-line arguments. * To be able to process unexpected events within a program. * To be able to allocate memory dynamically for arrays using C-style dynamic memory allocation. * To be able to resize memory dynamically allocated using C-style dynamic memory allocation.
Global variables should be avoided unless application performance is critical because they violate the principle of least privilege, and they make software difficult to maintain.

Creating programs in multiple source files facilitates software reusability and good software engineering. Functions may be common to many applications. In such instances, those functions should be
stored in their own source files, and each source file should have a corresponding header file containing function prototypes. This enables programmers of different applications to reuse the same code by including the proper
header file, and compiling their application with the corresponding source file.

The goto statement should be used only in performance-oriented applications. The goto statement is unstructured and can lead to programs that are more difficult to debug, maintain, and modify.
As with a struct or a class declaration, a union declaration simply creates a new type. Placing a union or struct declaration outside any function does not create a global variable.

Placing an ellipsis in the middle of a function parameter list. An ellipsis may only be placed at the end of the parameter list.

The result of referencing a union member other than the last one stored is undefined. It treats the stored data as the different type.

Initializing a union in a declaration with a value or an expression whose type is different from the type of the union's first member.

Comparing unions is a syntax error because the compiler does not know which member of each is active, and hence which member of one to compare to which member of the other.

18 C Legacy Code Topics
18.1Introduction
18.2Redirecting Input/Output on UNIX and DOS Systems
18.3Variable-Length Argument Lists
18.4Using Command-Line Arguments
18.5Notes on Compiling Multiple-Source-File Programs
18.6Program Termination with Exit and Atexit
18.7The Volatile Type Qualifier
18.8Suffixes for Integer and Floating-Point Constants
18.9Signal Handling
18.10Dynamic Memory Allocation: Functions Calloc and Realloc
18.11The Unconditional Branch: Goto
18.12Unions
18.13Linkage Specifications
18.14Summary
Terminology
Figures
18.1 Introduction
This chapter presents several advanced topics not ordinarily covered in introductory courses. Many of the capabilities discussed here are specific to particular operating systems, especially UNIX and/or DOS. Much of the material is for the benefit of C++ programmers who will need to work with older C legacy code.
18.2 Redirecting Input/Output on UNIX and DOS Systems
Normally the input to a program is from the keyboard (standard input), and the output from a program is displayed on the screen (standard output). On most computer systems--UNIX and DOS systems in particular--it is possible to redirect inputs to come from a file, and redirect outputs to be placed in a file. Both forms of redirection can be accomplished without using the file processing capabilities of the standard library.
There are several ways to redirect input and output from the UNIX command line. Consider the executable file sum that inputs integers one at a time and keeps a running total of the values until the end-of-file indicator is set, then prints the result. Normally the user inputs integers from the keyboard and enters the end-of-file key combination to indicate that no further values will be input. With input redirection, the input can be stored in a file. For example, if the data is stored in file input, the command line

$ sum < input

causes program sum to be executed; the redirect input symbol (<) indicates that the data in file input (instead
of the keyboard) is to be used as input by the program. Redirecting input on a DOS system is performed identically.
Note that $ is the UNIX command line prompt (some UNIX systems use a % prompt). Students often find it difficult to understand that redirection is an operating system function, not another C++ feature.
The second method of redirecting input is piping. A pipe (|) causes the output of one program to be redirected as the input to another program. Suppose program random outputs a series of random integers; the output of random can be "piped" directly to program sum using the UNIX command line

$ random | sum

This causes the sum of the integers produced by random to be calculated. Piping can be performed in UNIX and DOS.
Program output can be redirected to a file by using the redirect output symbol (>) (the same symbol is used for UNIX and DOS). For example, to redirect the output of program random to file out, use

$ random > out

Finally, program output can be appended to the end of an existing file by using the append output symbol (>>) (the same symbol is used for UNIX and DOS). For example, to append the output from program random
to file out created in the preceding command line, use the command line

$ random >> out

18.3 Variable-Length Argument Lists
[Note: This material is included for the benefit of C++ programmers who will work with C legacy code. In C++, programmers use function overloading to accomplish much of what C programmers accomplish with variable-length argument lists.] It is possible to create functions that receive an unspecified number of arguments. An ellipsis (...) in a function's prototype indicates that the function receives a variable number of arguments of any type. Note that the ellipsis must always be placed at the end of the parameter list, and there must be at least one named parameter. The macros
and definitions of the variable arguments header stdarg.h (Fig. 18.1) provide the capabilities necessary to build functions with variable-length argument lists.
The program of Fig. 18.2 demonstrates function average that receives a variable number of arguments. The first argument of average is always the number of values to be averaged.
Function average uses all the definitions and macros of header stdarg.h. Object ap, of type va_list, is used by macros va_start, va_arg, and va_end to process the variable-length argument list of function average. The function begins by invoking va_start to initialize object ap for use in va_arg and va_end. The macro receives
two arguments--object ap and the identifier of the rightmost argument in the argument list before the ellipsis--i in this case (va_start uses i here to determine where the variable-length argument list begins). Next, function average repeatedly adds the arguments in the variable-length argument list to variable total. The value to be added to total is retrieved from the argument list by invoking macro va_arg. Macro va_arg receives two arguments--object ap, and the type of the value expected in the argument list--double in this case. The macro returns the value of the argument. Function average invokes macro va_end with object ap as an argument to facilitate a
normal return to main from average. Finally, the average is calculated and returned to main. Note that we used only double arguments for the variable-length portion of the argument list. Actually, any data type or a mixture of data types can be used as long as the proper type is specified each time va_arg is used.
Drag the correct identifier to the box associated with the identifier:

A macro that is invoked before accessing a variable-length argument list.
A macro that facilitates normal return from a function with a variable length argument list.
To access the arguments in a variable length argument list, a maco of this type must be created.
A macro that expands to an expression of the value and type of the next argument.
18.4 Using Command-Line Arguments
On many systems--DOS and UNIX in particular--it is possible to pass arguments to main from a command line by including parameters int argc and char *argv[] in the parameter list of main. Parameter argc receives the number of command-line arguments. Parameter argv is an array of strings in which the actual command-line arguments are stored. Common uses of command-line arguments include printing the arguments, passing options to a program, and passing filenames to a program.
The program of Fig. 18.3 copies a file into another file one character at a time. The executable file for the program is called copy. A typical command line for the copy program on a UNIX system is

$ copy input output

This command line indicates that file input is to be copied to file output. When the program executes, if argc is not 3 (copy counts as one of the arguments), the program prints an error message and terminates. Otherwise, array argv contains the strings "copy", "input" and "output". The second and third arguments on the command line are used as file names by the program. The files are opened by creating
ifstream object inFile and ofstream object outFile. If both files are opened successfully, characters are read from file input with member function get and written to file output with member function put until the end- of-file indicator for file input is set. Then the program terminates. The result is an exact copy of file input. Note that not all computer systems support command- line arguments as easily as UNIX and DOS. Macintosh and VMS systems, for example, require special settings for processing command-line arguments. See the manuals for your system for more information on command-line arguments.
Drag the correct identifier to the box associated with the identifier:

The name of the argument to main that is an array of strings representing the command-line arguments.
The name of the argument that represents the number of command-line arguments passed to main.
18.5 Notes on Compiling Multiple-Source- File Programs
As stated earlier in the text, it is possible to build programs that consist of multiple source files (see Chapter 6, "Classes and Data Abstraction"). There are several considerations when creating programs in multiple files. For example, the definition of a function must be entirely contained in one file--it cannot span two or more files.
In Chapter 3, we introduced the concepts of storage class and scope. We learned that variables declared outside any function definition are of storage class
static by default and are referred to as global variables. Global variables are accessible to any function defined in the same file after the variable is declared. Global variables also are accessible to functions in other files, however, the global variables must be declared in each file in which they are used. For example, if we define global integer variable flag in one file, and refer to it in a second file, the second file must contain the declaration

extern int flag;

prior to the variable's use in that file. In the preceding declaration, the storage class specifier extern indicates to the compiler that variable flag is defined
either later in the same file or in a different file. The compiler informs the linker that unresolved references to variable flag appear in the file (the compiler does not know where the flag is defined, so it lets the linker attempt to find flag). If the linker cannot locate a definition of flag, a linker error is reported, and no executable file is produced. If a proper global definition is located, the linker resolves the references by indicating where flag is located.
Just as extern declarations can be used to declare global variables to other program files, function prototypes can extend the scope of a function beyond the file in which it is defined (the extern specifier is not required
in a function prototype). This is accomplished by including the function prototype in each file in which the function is invoked, and compiling the files together (see Section 17.2). Function prototypes indicate to the compiler that the specified function is defined either later in the same file or in a different file. The compiler does not attempt to resolve references to such a function--that task is left to the linker. If the linker cannot locate a function definition, an error is generated.
As an example of using function prototypes to extend the scope of a function, consider any program containing the preprocessor directive #include
<string.h>. This directive includes in a file the function prototypes for functions such as strcmp and strcat. Other functions in the file can use strcmp and strcat to accomplish their tasks. The strcmp and strcat functions are defined for us separately. We do not need to know where they are defined. We are simply reusing the code in our programs. The linker resolves our references to these functions automatically. This process enables us to use the functions in the standard library.
It is possible to restrict the scope of a global variable or function to the file in which it is defined. The storage class specifier static, when applied to a global variable
or a function, prevents it from being used by any function that is not defined in the same file. This is referred to as internal linkage. Global variables and functions that are not preceded by static in their definitions have external linkage--they can be accessed in other files if those files contain proper declarations and/or function prototypes.
The global variable declaration

static float pi = 3.14159;

creates variable pi of type float, initializes it to 3.14159, and indicates that pi is known only to functions in the file in which it is defined.
The static specifier is commonly used with utility functions that are called only by functions in a particular file. If a function is not required outside a particular file, the principle of least privilege should be enforced by using static. If a function is defined before it is used in a file, static should be applied to the function definition. Otherwise, static should be applied to the function prototype.
When building large programs in multiple source files, compiling the program becomes tedious if small changes are made to one file, and the entire program must be recompiled. Many systems provide special utilities that recompile only the modified program file.
On UNIX systems the utility is called make. Utility make reads a file called makefile that contains instructions for compiling and linking the program. Systems such as Borland C++ and Microsoft Visual C++ for PCs provide make utilities and "projects". For more information on make utilities, see the manual for your particular system.
Select the true statement(s).
Functions and global variables have internal linkage if they are declared as static.
Unix utility make reads a file called a makefile that contains instructions for compiling and linking multiple source files.
Global variables are accessible to other files in a programwithout the need for a storage class specifier.
18.6 Program Termination with Exit and Atexit
The general utilities library (stdlib.h) provides methods of terminating program execution other than a conventional return from function main. Function exit forces a program to terminate as if it executed normally. The function often is used to terminate a program when an error is detected in the input, or if a file to be processed by the program cannot be opened. Function atexit registers a function in the program to be called upon successful termination of the program--i.e., either
when the program terminates by reaching the end of main, or when exit is invoked.
Function atexit takes a pointer to a function (i.e., the function name) as an argument. Functions called at program termination cannot have arguments, and cannot return a value. Up to 32 functions may be registered for execution at program termination.
Function exit takes one argument. The argument is normally the symbolic constant EXIT_SUCCESS or the symbolic constant EXIT_FAILURE. If exit is called with EXIT_SUCCESS, the implementation- defined value for successful termination is returned to the calling environment. If exit is called with
EXIT_FAILURE, the implementation-defined value for unsuccessful termination is returned. When function exit is invoked, any functions previously registered with atexit are invoked in the reverse order of their registration, all streams associated with the program are flushed and closed, and control returns to the host environment. The program of Fig. 18.4 tests functions exit and atexit. The program prompts the user to determine whether the program should be terminated with exit or by reaching the end of main. Note that function print is executed at program termination in each case.
Select the true statement(s).
Functions that are registered to be called at termination by atexit take a string argument which is displayed.
Function exit normally takes either EXIT_FAILURE or EXIT_SUCCESS as an argument.
18.7 The Volatile Type Qualifier
The volatile type qualifier is applied to a definition of a variable that may be altered from outside the program (i.e., the variable is not completely under the control of the program). Thus, the compiler cannot perform optimizations (such as speeding program execution or reducing memory consumption, for example) that depend on "knowing a variable's behavior is influenced only by program activities the compiler can observe."
18.8 Suffixes for Integer and Floating-Point Constants
C++ provides integer and floating-point suffixes for specifying the types of integer and floating-point constants. The integer suffixes are: u or U for an unsigned integer, l or L for a long integer, and ul or UL for an unsigned long integer. The following constants are of type unsigned, long, and unsigned long, respectively:

174u

8358L

28373ul

If an integer constant is not suffixed, its type is determined by the first type capable of storing a value of that size (first int, then long int, then unsigned long int).
The floating-point suffixes are: f or F for a float, and l or L for a long double. The following constants are of type long double and float, respectively:

3.14159L

1.28f

A floating-point constant that is not suffixed is automatically of type double.
Drag the correct suffix to the box associated with the suffix:

Suffix that indicates an unsigned int constant.
Suffix that indicates a float constant.
Suffix that indicates an unsigned long constant.
Suffix that indicates a long constant.
18.9 Signal Handling
An unexpected event, or signal, can terminate a program prematurely. Some unexpected events include interrupts (typing <ctrl> c on a UNIX or DOS system), illegal instructions, segmentation violations, termination orders from the operating system, and floating-point exceptions (division by zero or multiplying large floating-point values). The signal handling library provides function signal to trap unexpected events. Function signal receives two arguments--an integer signal number and a pointer to the signal handling function. Signals can be generated
by function raise which takes an integer signal number as an argument. Figure 18.5 summarizes the standard signals defined in header file signal.h. The program of Fig. 18.6 demonstrates functions signal and raise.
Figure 18.6 traps an interactive signal (SIGINT) with function signal. The program calls signal with SIGINT and a pointer to function signal_handler (remember that the name of a function is a pointer to the the function). Now, when a signal of type SIGINT occurs, function signal_handler is called, a message is printed, and the user is given the option to continue normal execution of the program. If the user wishes to continue execution, the signal handler is reinitialized by calling
signal again (some systems require the signal handler to be reinitialized), and control returns to the point in the program at which the signal was detected. In this program, function raise is used to simulate an interactive signal. A random number between 1 and 50 is chosen. If the number is 25, then raise is called to generate the signal. Normally, interactive signals are initiated outside the program. For example, typing <ctrl> c during program execution on a UNIX or DOS system generates an interactive signal that terminates program execution. Signal handling can be used to trap the interactive signal and prevent the program from terminating.
Drag the correct term to the box associated with the term:

Function that can be invoked to signal the program.
Header file to include to use the signal and raise capabilities.
Function called to register a signal handler.
Symbolic constant that represents an interrupt signal.
18.10 Dynamic Memory Allocation: Functions Calloc and Realloc
In Chapter 7, when we discussed C++-style dynamic memory allocation with new and delete, we compared new and delete with the C functions malloc and free. C++ programmers should use new and delete not malloc and free. However, most C++ programmers will find themselves reading a great deal of C legacy code, and therefore we include this additional discussion on C-style dynamic memory allocation.
The general utilities library (stdlib.h) provides two other functions for dynamic memory allocation--calloc
and realloc. These functions can be used to create and modify dynamic arrays. As shown in Chapter 5, "Pointers and Strings," a pointer to an array can be subscripted like an array. Thus, a pointer to a contiguous portion of memory created by calloc can be manipulated as an array. Function calloc dynamically allocates memory for an array. The prototype for calloc is

void *calloc( size_t nmemb, size_t size );

It receives two arguments--the number of elements (nmemb) and the size of each element (size)--and initializes the elements of the array to zero. The
function returns a pointer to the allocated memory, or a null pointer (0) if the memory is not allocated.
Function realloc changes the size of an object allocated by a previous call to malloc, calloc or realloc. The original object's contents are not modified provided that the memory allocated is larger than the amount allocated previously. Otherwise, the contents are unchanged up to the size of the new object. The prototype for realloc is

void *realloc( void *ptr, size_t size );

Function realloc takes two arguments--a pointer to the original object (ptr) and the new size of the object (size). If ptr is 0, realloc works identically to malloc. If
size is 0 and ptr is not 0, the memory for the object is freed. Otherwise, if ptr is not 0 and size is greater than zero, realloc tries to allocate a new block of memory for the object. If the new space cannot be allocated, the object pointed to by ptr is unchanged. Function realloc returns either a pointer to the reallocated memory, or a null pointer.
Select the C++ statement that does not generate an error.
char *cPtr=static_cast<char *>(calloc(3, 1));.
char cPtr = calloc(3, 1);.
char *cPtr = static_cast<char>( calloc( 3 ) ).
char *cPtr = calloc(sizeof( char * ) * 3);.
18.11 The Unconditional Branch: Goto
Throughout the text we have stressed the importance of using structured programming techniques to build reliable software that is easy to debug, maintain, and modify. In some cases, performance is more important than strict adherence to structured programming techniques. In these cases, some unstructured programming techniques may be used. For example, we can use break to terminate execution of a repetition structure before the loop continuation condition becomes false. This saves unnecessary repetitions of
the loop if the task is completed before loop termination.
Another instance of unstructured programming is the goto statement--an unconditional branch. The result of the goto statement is a change in the flow of control of the program to the first statement after the label specified in the goto statement. A label is an identifier followed by a colon. A label must appear in the same function as the goto statement that refers to it. The program of Fig. 18.7 uses goto statements to loop ten times and print the counter value each time. After initializing count to 1, the program tests count to determine whether it is greater than 10 (the label start
is skipped because labels do not perform any action). If so, control is transferred from the goto to the first statement after the label end. Otherwise, count is printed and incremented, and control is transferred from the goto to the first statement after the label start.
In Chapter 2, we stated that only three control structures are required to write any program--sequence, selection, and repetition. When the rules of structured programming are followed, it is possible to create deeply nested control structures from which it is difficult to efficiently escape. Some programmers use goto statements in such situations as a quick exit from a
deeply nested structure. This eliminates the need to test multiple conditions to escape from a control structure.
Select the statement that does not generate an error.
goto (x).
goto x;.
goto x:.
goto x:;.
18.12 Unions
A union (defined with keyword union) is a region of memory that, over time, can contain objects of a variety of types. However, at any moment, a union can contain a maximum of one object because the members of a union share the same storage space. It is the programmer's responsibility to ensure that the data in a union is referenced with a member name of the proper data type.
At different times during a program's execution, some objects may not be relevant, but one other object is--so a union shares the space instead of wasting storage on
objects that are not being used. The number of bytes used to store a union must be at least enough to hold the largest member.
A union is declared in the same format as a struct or a class. The union declaration

union Number {

int x;

float y;

};

indicates that Number is a union type with members int x and float y. The union definition normally precedes main in a program so the definition can be used to declare variables in all the program's functions.
The only valid built-in operations that can be performed on a union are: assigning a union to another union of the same type, taking the address (&) of a union, and accessing union members using the structure member operator (.) and the structure pointer operator (->). unions may not be compared for the same reasons that structures cannot be compared.
A union is similar to a class in that it can have a constructor to initialize any of its members. A union that has no constructor can be initialized with another union of the same type, with an expression of the type of the first member of the union, or with an initializer (enclosed in braces) of the type of the first member of
the union. unions can have other member functions, such as destructors, but a union's member functions cannot be declared virtual. The members of a union are public by default.
A union cannot be used as a base class in inheritance, i.e., classes may not be derived from unions. unions can have objects as members only if these objects do not have a constructor, a destructor, or an overloaded assignment operator. None of a union's data members can be declared static.
The program in Fig. 18.8 uses the variable value of type union number to display the value stored in the union as both an int and a float. The program output is
implementation dependent. The program output shows that the internal representation of a float value can be quite different from the representation of an int.
An anonymous union is a union without a type name, that does not attempt to define objects or pointers before its terminating semicolon. Such a union does not create a type but does create an unnamed object. An anonymous union's members may be accessed directly in the scope in which the anonymous union is declared just as any other local variable--there is no need to use the dot (.) or arrow (->) operators.
Anonymous unions have some restrictions. Anonymous unions can contain only data members. All
members of an anonymous union must be public. And, an anonymous union declared globally (i.e., at file scope) must be explicitly declared static.
Figure 18.9 illustrates the use of an anonymous union.
Select the true statement(s).
The members of a union are private by default.
All union members share the same address space.
Unlike structs or classes, union definitions must be placed in a header file.
An anonymous union is a union without a type name, that does not attempt to define objects or pointers before its terminating semicolon.
18.13 Linkage Specifications
It is possible from a C++ program to call functions written and compiled with a C compiler. As stated in Section 3.20, C++ specially encodes function names for type-safe linkage. C, however, does not encode its function names. Thus, a function compiled in C will not be recognized when an attempt is made to link C code with C++ code because the C++ code expects a specially encoded function name. C++ enables the programmer to provide linkage specifications to inform the compiler that a function was compiled on a C compiler, and to prevent the name of the function from
being encoded by the C++ compiler. Linkage specifications are useful when large libraries of specialized functions have been developed, and the user either does not have access to the source code for recompilation into C++ or time to convert the library functions from C to C++.
To inform the compiler that one or several functions have been compiled in C, write the function prototypes as follows:

extern "C" function prototype   // single function

extern "C" // multiple functions

{


   function prototypes

}

These declarations inform the compiler that the specified functions are not compiled in C++, so name encoding should not be performed on the functions listed in the linkage specification. These functions can then be linked properly with the program. C++ environments normally include the standard C libraries and do not require the programmer to use linkage specifications for those functions.
18.14 Summary
* On many systems--UNIX and DOS systems in particular--it is possible to redirect input to a program and output from a program. Input is redirected from the UNIX and DOS command lines using the redirect input symbol (<) or using a pipe (|). Output is redirected from the UNIX and DOS command lines using the redirect output symbol (>) or the append output symbol (>>). The redirect output symbol simply stores the program output in a file and the append output symbol appends the output to the end of a file. * The macros and definitions of the variable arguments
* header stdarg.h provide the capabilities necessary to build functions with variable-length argument lists. * An ellipsis (...) in a function prototype indicates that the function receives a variable number of arguments. * Type va_list is suitable for holding information needed by macros va_start, va_arg, and va_end. To access the arguments in a variable-length argument list, an object of type va_list must be declared. * Macro va_start is invoked before the arguments of a variable-length argument list can be accessed. The macro initializes the object declared with va_list for use by the va_arg and va_end macros. * Macro va_arg expands to an expression of the value * and type of the next argument in the variable-length argument list. Each invocation of va_arg modifies the object declared with va_list so that the object points to the next argument in the list. * Macro va_end facilitates a normal return from a function whose variable argument list was referred to by the va_start macro. * On many systems--DOS and UNIX in particular--it is possible to pass command-line arguments to main by including in main's parameter list the parameters int argc and char *argv[]. Parameter argc is the number of command-line arguments. Parameter argv is an array of strings containing the command-line arguments. * The definition of a function must be entirely contained in one file--it cannot span two or more files. * Global variables must be declared in each file in which they are used. * Function prototypes can extend the scope of a function beyond the file in which it is defined (the extern specifier is not required in a function prototype). This is accomplished by including the function prototype in each file in which the function is invoked and compiling the files together. * The storage class specifier static, when applied to a global variable or a function, prevents it from being used by any function that is not defined in the same file. * This is referred to as internal linkage. Global variables and functions that are not preceded by static in their definitions have external linkage--they can be accessed in other files if those files contain proper declarations and/or function prototypes. * The static specifier is commonly used with utility functions that are called only by functions in a particular file. If a function is not required outside a particular file, the principle of least privilege should be enforced by using static. * When building large programs in multiple source files, compiling the program becomes tedious if small changes are made to one file, and the entire program * must be recompiled. Many systems provide special utilities that recompile only the modified program file. On UNIX systems the utility is called make. Utility make reads a file called makefile that contains instructions for compiling and linking the program. * Function exit forces a program to terminate as if it executed normally. * Function atexit registers a function in a program to be called upon normal termination of the program--i.e., either when the program terminates by reaching the end of main or when exit is invoked. * Function atexit takes a pointer to a function (i.e., a function name) as an argument. Functions called at pro * gram termination cannot have arguments, and cannot return a value. Up to 32 functions may be registered for execution at program termination. * Function exit takes one argument. The argument is normally the symbolic constant EXIT_SUCCESS or the symbolic constant EXIT_FAILURE. If exit is called with EXIT_SUCCESS, the implementation- defined value for successful termination is returned to the calling environment. If exit is called with EXIT_FAILURE, the implementation-defined value for unsuccessful termination is returned. * When function exit is invoked, any functions registered with atexit are invoked in the reverse order of * their registration, all streams associated with the program are flushed and closed, and control returns to the host environment. * The volatile qualifier is used to prevent optimizations of a variable because it can be modified from outside the program's scope. * C++ provides integer and floating-point suffixes for specifying the types of integer and floating-point constants. The integer suffixes are: u or U for an unsigned integer, l or L for a long integer, and ul or UL for an unsigned long integer. If an integer constant is not suffixed, its type is determined by the first type capable of storing a value of that size (first int, then long int, then * unsigned long int). The floating-point suffixes are: f or F for a float, and l or L for a long double. A floating- point constant that is not suffixed is of type double. * The signal handling library provides the capability to trap unexpected events with function signal. Function signal receives two arguments--an integer signal number and a pointer to the signal handling function. * Signals can also be generated with function raise and an integer argument. * The general utilities library (stdlib.h) provides functions calloc and realloc for dynamic memory allocation. These functions can be used to create dynamic arrays. * Function calloc receives two arguments--the number of elements (nmemb) and the size of each element (size)--and initializes the elements of the array to zero. The function returns either a pointer to the allocated memory, or a NULL pointer if the memory is not allocated. * Function realloc changes the size of an object allocated by a previous call to malloc, calloc, or realloc. The original object's contents are not modified provided that the amount of memory allocated is larger than the amount allocated previously. * Function realloc takes two arguments--a pointer to the original object (ptr) and the new size of the object * (size). If ptr is NULL, realloc works identically to malloc. If size is 0 and the pointer received is not NULL, the memory for the object is freed. Otherwise, if ptr is not NULL and size is greater than zero, realloc tries to allocate a new block of memory for the object. If the new space cannot be allocated, the object pointed to by ptr is unchanged. Function realloc returns either a pointer to the reallocated memory, or a NULL pointer. * The result of the goto statement is a change in the program's flow of control. Program execution continues at the first statement after the label in the goto statement. * A label is an identifier followed by a colon. A label * must appear in the same function as the goto statement that refers to it. * A union is a derived data type whose members share the same storage space. The members can be any type. The storage reserved for a union is large enough to store its largest member. In most cases, unions contain two or more data types. Only one member, and thus one data type, can be referenced at a time. * A union is declared in the same format as a structure. * A union can be initialized only with a value of the type of its first member. * C++ enables the programmer to provide linkage specifications to inform the compiler that a function * was compiled on a C compiler, and to prevent the name of the function from being encoded by the C++ compiler. * To inform the compiler that one or several functions have been compiled in C, write the function prototypes as follows:
extern "C" function prototype   // single function

extern "C" // multiple functions

{

function prototypes

}

* These declarations inform the compiler that the specified functions are not compiled in C++, so name
* encoding should not be performed on the functions listed in the linkage specification. These functions can then be linked properly with the program. * C++ environments normally include the standard C libraries and do not require the programmer to use linkage specifications for those functions.
This chapter does not contain any Testing and Debugging tips.
This chapter does not contain any Applet Examples.
This chapter does not contain any Good Programming Practices tips.